--[[
	Plugable frame for compactly displaying ScanResults.
	
	Copyright (C) Udorn (Blackhand)
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.	
--]]

vendor.CompactScanResultFrame = {}
vendor.CompactScanResultFrame.prototype = {}
vendor.CompactScanResultFrame.metatable = {__index = vendor.CompactScanResultFrame.prototype}

local L = vendor.Locale.GetInstance()

local NAME_SORT = "name";
local COUNT_SORT = "count";
local OWNER_SORT = "owner";
local BID_SORT = "bidPerItem";
local BUYOUT_SORT = "buyoutPerItem";

--[[
	Updates the arrow indicator of the given button.
--]]
local function _UpdateArrow(self, bt, sortType)
	local arrow = getglobal(bt:GetName().."Arrow");
	if (sortType == self.sortType) then
		arrow:Show();
		if (not self.isAscending) then
			arrow:SetTexCoord(0, 0.5625, 1.0, 0);
		else
			arrow:SetTexCoord(0, 0.5625, 0, 1.0);
		end
	else
		arrow:Hide();
	end
end

--[[
	Updates the state of the sort buttons.
--]]
local function _UpdateSortButtons(self)
	_UpdateArrow(self, self.nameSort, NAME_SORT);
	_UpdateArrow(self, self.countSort, COUNT_SORT);
	_UpdateArrow(self, self.ownerSort, OWNER_SORT);
	_UpdateArrow(self, self.bidSort, BID_SORT);
	_UpdateArrow(self, self.buyoutSort, BUYOUT_SORT);
end

--[[
	Callback for updating the browse scrollbar.
--]]
local function _BrowseUpdate(selfIn)
	local self = selfIn.ctrl or selfIn;
	if (not self or not self.scanResult) then
		FauxScrollFrame_Update(self.browseScroll, 0, 1, AUCTIONS_BUTTON_HEIGHT);
		return;
	end
	_UpdateSortButtons(self);
	-- display wheter we have results
	local n = self.scanResult:Size();
	if (n == 0) then
		self.noResultsText:Show();
	else
		self.noResultsText:Hide();
	end

	-- traverse the items to be displayed
	local offset = FauxScrollFrame_GetOffset(self.browseScroll);	
	for i=1, self.numItems do
		local index = offset + i;
		local button = self.browseButs[i];
		-- Show or hide auction buttons
		if (index > n) then
			button:Hide();
		else
			button:Show();
			local buttonName = button:GetName();
			local itemLinkKey, time, timeLeft, count, minBid, minIncrement, buyoutPrice, bidAmount, owner = self.scanResult:Get(index);
			assert(bidAmount);
			assert(buyoutPrice);
			local itemLink = vendor.Items:GetItemLink(itemLinkKey);
			local name, _, rarity, level, minLevel, itemType, subType, stackCount, equipLoc, texture = GetItemInfo(itemLink);
			assert(name); -- TODO handle nil with subfunction
			
			local color = ITEM_QUALITY_COLORS[rarity];
			local itemName = getglobal(buttonName.."Name");
			itemName:SetText(name);
			itemName:SetVertexColor(color.r, color.g, color.b);
			itemCount = getglobal(buttonName.."Count");
			itemCount:SetText(count);

			local bt = getglobal(buttonName.."Owner");
			bt:SetText(owner);
						
			local bid = minBid;
			if (bidAmount and bidAmount > 0) then
				bid = bidAmount;
			end
			
			bt = getglobal(buttonName.."Bid");
			local msg = vendor.Format.FormatMoney(bid / count, true);
			if (count > 1) then
				msg = msg.." ("..vendor.Format.FormatMoney(bid, true)..")";
			end
			bt:SetText(msg);
			
			bt = getglobal(buttonName.."Buyout");
			msg = "";
			if (buyoutPrice > 0) then
				msg = vendor.Format.FormatMoney(buyoutPrice / count, true);
				if (count > 1) then
					msg = msg.."("..vendor.Format.FormatMoney(buyoutPrice, true)..")";
				end
			end
			bt:SetText(msg);
			
			-- Resize according to scroller presence resp. absence
			if (n <= self.numItems) then
				bt:SetWidth(155);
				self.buyoutSort:SetWidth(160);
			else
				bt:SetWidth(131);
				self.buyoutSort:SetWidth(134);
			end
		end
	end
	-- Update scrollFrame
	FauxScrollFrame_Update(self.browseScroll, n, self.numItems, AUCTIONS_BUTTON_HEIGHT);
	if (self.scanResult and self.scanResult:Size() > 0) then
		-- 0 seconds lead to an empty string
		local secs = SecondsToTime(self.scanResult:GetUpToDateness() + 1);
		local msg = L["Up-to-dateness: <= "]..secs
		local itemLink = self.scanResult:GetItemLink()
		if (itemLink) then
			-- get averages
			local minBid, buyout = vendor.Statistic:GetCurrentAuctionInfo(itemLink, vendor.AuctionHouse:IsNeutral())
			local minBidMsg = "-"
			local buyoutMsg = "-"
			if (minBid and minBid > 0) then
				minBidMsg = vendor.Format.FormatMoney(minBid)
			end
			if (buyout and buyout > 0) then
				buyoutMsg = vendor.Format.FormatMoney(buyout)
			end
			if ( GetLocale() == "zhTW" or GetLocale() == "zhCN" ) then
				msg = msg.." - ("..minBidMsg.."/"..buyoutMsg..")"
			else
				msg = msg.." - Ø("..minBidMsg.."/"..buyoutMsg..")"
			end
		end
		self.statusText:SetText(msg)
	else
		self.statusText:SetText("");
	end
end


--[[
	Toggles the sort state for the given type. If it's currently not
	the sorting criteria, then it will be activated and set to ascending.
--]]
local function _ToggleSort(self, bt, sortType)
	if (sortType == self.sortType) then
		self.isAscending = not self.isAscending;
	else
		self.sortType = sortType;
		self.isAscending = true;
	end
	_UpdateSortButtons(self);
	if (self.scanResult) then
		self.scanResult:Sort(self.sortType, self.isAscending);
	end
	_BrowseUpdate(self);
end

local function _Init(self, name, parent, numItems, statusText)
	vendor.CompactScanResultFrame.super.prototype.init(self)
	self.statusText = statusText;
	self.numItems = numItems;
	self.scanResult = nil;
	self.browseButs = {};
	self.frame = CreateFrame("Frame", name, parent);
	self.frame:SetWidth(658);
	self.frame:SetHeight(347);	
	for i=1, numItems do
		local but = CreateFrame("Button", name.."BrowseButton"..i, self.frame, "CompactScanResultTemplate");
		but:SetID(i);
		if (i == 1) then
			but:SetPoint("TOPLEFT", 195, -110);
		else
			but:SetPoint("TOPLEFT", name.."BrowseButton"..(i-1), "BOTTOMLEFT", 0, 0);
		end
		but:Hide();
		self.browseButs[i] = but;
	end
	
	-- no results text
	self.noResultsText = self.frame:CreateFontString(name.."NoResultsText", "ARTWORK", "GameFontNormal");
	self.noResultsText:SetText(L["Found no auctions, press \"Refresh\" to update the list."]);
	self.noResultsText:SetPoint("TOP", 115, -120);
	self.noResultsText:Hide();
	
	-- scrollframe
	self.browseScroll = CreateFrame("ScrollFrame", name.."BrowseScrollFrame", parent, "FauxScrollFrameTemplate");
	self.browseScroll.ctrl = self;
	self.browseScroll:SetWidth(465);
	self.browseScroll:SetHeight(333);
	self.browseScroll:SetPoint("TOPRIGHT", 39, -78);
	self.browseScroll:SetScript("OnVerticalScroll", function(but, value) FauxScrollFrame_OnVerticalScroll(but, value, AUCTIONS_BUTTON_HEIGHT, _BrowseUpdate); end);
	self.browseScroll:SetScript("OnShow", function(but) _BrowseUpdate(but.ctrl); end);
	
	local t = self.browseScroll:CreateTexture(nil, "ARTWORK");
	t:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar");
	t:SetWidth(31);
	t:SetHeight(256);
	t:SetPoint("TOPLEFT", self.browseScroll, "TOPRIGHT", -2, 5);
	t:SetTexCoord(0, 0.484375, 0, 1.0);

	t = self.browseScroll:CreateTexture(nil, "ARTWORK");
	t:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar");
	t:SetWidth(31);
	t:SetHeight(106);
	t:SetPoint("BOTTOMLEFT", self.browseScroll, "BOTTOMRIGHT", -2, -2);
	t:SetTexCoord(0.515625, 1.0, 0, 0.4140625);
	
	-- sort buttons
	local bt1 = CreateFrame("Button", name.."NameSort", self.frame, "AuctionSortButtonTemplate");
	bt1:SetText(L["Name"]);
	bt1:SetPoint("TOPLEFT", 190, -85);
	bt1:SetWidth(197);
	bt1:SetHeight(19);
	bt1.ctrl = self;
	-- no name sorting needed (and possible)
	--bt1:SetScript("OnClick", function() _ToggleSort(this.ctrl, this, NAME_SORT); end);
	self.nameSort = bt1;
	
	local bt2 = CreateFrame("Button", name.."CountSort", self.frame, "AuctionSortButtonTemplate");
	bt2:SetText(L["Itms."]);
	bt2:SetPoint("LEFT", bt1, "RIGHT", -2, 0);
	bt2:SetWidth(45);
	bt2:SetHeight(19);
	bt2.ctrl = self;
	bt2:SetScript("OnClick", function(but) _ToggleSort(but.ctrl, but, COUNT_SORT); end);
	self.countSort = bt2;
	
	local bt3 = CreateFrame("Button", name.."OwnerSort", self.frame, "AuctionSortButtonTemplate");
	bt3:SetText(L["Seller"]);
	bt3:SetPoint("LEFT", bt2, "RIGHT", -2, 0);
	bt3:SetWidth(80);
	bt3:SetHeight(19);
	bt3.ctrl = self;
	bt3:SetScript("OnClick", function(but) _ToggleSort(but.ctrl, but, OWNER_SORT); end);
	self.ownerSort = bt3;
	
	local bt4 = CreateFrame("Button", name.."BidSort", self.frame, "AuctionSortButtonTemplate");
	bt4:SetText(L["Bid"]);
	bt4:SetPoint("LEFT", bt3, "RIGHT", -2, 0);
	bt4:SetWidth(133);
	bt4:SetHeight(19);
	bt4.ctrl = self;
	bt4:SetScript("OnClick", function(but) _ToggleSort(but.ctrl, but, BID_SORT); end);
	self.bidSort = bt4;
	
	local bt5 = CreateFrame("Button", name.."BuyoutSort", self.frame, "AuctionSortButtonTemplate");
	bt5:SetText(L["Buyout"]);
	bt5:SetPoint("LEFT", bt4, "RIGHT", -2, 0);
	bt5:SetWidth(160);
	bt5:SetHeight(19);
	bt5.ctrl = self;
	bt5:SetScript("OnClick", function(but) _ToggleSort(but.ctrl, but, BUYOUT_SORT); end);
	self.buyoutSort = bt5;
					
	-- We want to sort according to the buyouts
	_ToggleSort(self, self.bidSort, BUYOUT_SORT);
	
	-- register for new ScanResults
	vendor.Scanner:AddScanSnapshotListener(self);
end

--[[ 
	Creates a new instance.
--]]
function vendor.CompactScanResultFrame:new(name, parent, numItems, statusText)
	local instance = setmetatable({}, self.metatable)
	_Init(instance, name, parent, numItems, statusText)
	return instance
end

--[[
	Selects a new ScanSet to be displayed by this frame.
	Nothing will be displayed if nil is set.
--]]
function vendor.CompactScanResultFrame.prototype:Display(scanResult)
	self.scanResult = scanResult;
	if (scanResult) then
		self.scanResult:Sort(self.sortType, self.isAscending)
	end
	_BrowseUpdate(self);
end

--[[
	Update the currently displayed result list.
--]]
function vendor.CompactScanResultFrame.prototype:Update()
	_BrowseUpdate(self);
end

--[[
	Sets the position of the frame.
--]]
function vendor.CompactScanResultFrame.prototype:SetPoint(...)
	self.frame:SetPoint(...);
end

--[[
	ScanResultListener interface method for new or updated
	Scanresults.
--]]
function vendor.CompactScanResultFrame.prototype:ScanSnapshotUpdated(snapshot)
	vendor.Vendor:Debug("updated for compact result frame");
	if (self.scanResult) then
		self.scanResult = vendor.Scanner:GetScanSet(self.scanResult:IsNeutral(), self.scanResult:GetItemLink());
		self.scanResult:Sort(self.sortType, self.isAscending);
		_BrowseUpdate(self);
	end
end
